home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Dr. Windows 3
/
dr win3.zip
/
dr win3
/
NEW_TECH
/
MENTC.ZIP
/
SEARCH.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-04-18
|
43KB
|
1,787 lines
/*
* The functions in this file implement commands that search in the forward
* and backward directions.
*
* (History comments formerly here have been moved to history.c)
*
*/
#include <stdio.h>
#include "estruct.h"
#include "eproto.h"
#include "edef.h"
#include "elang.h"
/* The variables matchline and matchoff hold the line
* and offset position of the *start* of the match.
*/
static int matchlen;
static int matchoff;
static LINE *matchline;
static int patlenadd;
static int lastchfjump, lastchbjump;
static int deltaf[HICHAR], deltab[HICHAR];
static int replen; /* length of replacement string */
#if MAGIC
static int group_count;
static int group_len[MAXGROUPS];
static REGION group_reg[MAXGROUPS];
#endif
/*
* forwsearch -- Search forward. Get a search string from the user, and
* search for the string. If found, reset the "." to be just after
* the match string, and (perhaps) repaint the display.
*/
int PASCAL NEAR forwsearch(f, n)
int f, n; /* default flag / numeric argument */
{
register int status;
/* If n is negative, search backwards.
* Otherwise proceed by asking for the search string.
*/
if (n < 0)
return (backsearch(f, -n));
/* Ask the user for the text of a pattern. If the response is
* TRUE (responses other than FALSE are possible), search for
* pattern for up to n times, as long as the pattern is there
* to be found.
*/
if ((status = readpattern(TEXT78, &pat[0], TRUE)) == TRUE)
status = forwhunt(f, n);
/* "Search" */
return (status);
}
/*
* forwhunt -- Search forward for a previously acquired search string.
* If found, reset the "." to be just after the match string,
* and (perhaps) repaint the display.
*/
int PASCAL NEAR forwhunt(f, n)
int f, n; /* default flag / numeric argument */
{
register int spoint = PTEND;
register int status;
if (n < 0) /* search backwards */
return (backhunt(f, -n));
/* Make sure a pattern exists, or that we didn't switch
* into MAGIC mode after we entered the pattern.
*/
if (pat[0] == '\0') {
mlwrite(TEXT80);
/* "No pattern set" */
return FALSE;
}
#if MAGIC
if ((curwp->w_bufp->b_mode & MDMAGIC) && mcpat[0].mc_type == MCNIL) {
if (!mcstr())
return FALSE;
}
#endif
/*
* Do one extra search to get us past our current
* match, if the search type has us at the start
* of a match, instead of after a match.
*/
if (searchtype == SRBEGIN) {
spoint = PTBEG;
if (lastflag & CFSRCH)
n = (n > 2)? (n + 1): 2;
}
#if MAGIC
if (magical && (curwp->w_bufp->b_mode & MDMAGIC))
status = mcscanner(FORWARD, spoint, n);
else
#endif
status = scanner(FORWARD, spoint, n);
/* Complain if not there.
*/
if (status == FALSE)
mlwrite(TEXT79);
/* "Not found" */
thisflag |= CFSRCH;
return (status);
}
/*
* backsearch -- Reverse search. Get a search string from the user, and
* search, starting at "." and proceeding toward the front of the buffer.
* If found "." is left pointing at the first character of the pattern
* (the last character that was matched).
*/
int PASCAL NEAR backsearch(f, n)
int f, n; /* default flag / numeric argument */
{
register int status;
/* If n is negative, search forwards.
* Otherwise proceed by asking for the search string.
*/
if (n < 0)
return (forwsearch(f, -n));
/* Ask the user for the text of a pattern. If the response is
* TRUE (responses other than FALSE are possible), search for
* pattern for up to n times, as long as the pattern is there
* to be found.
*/
if ((status = readpattern(TEXT81, &pat[0], TRUE)) == TRUE)
status = backhunt(f, n);
/* "Reverse search" */
return (status);
}
/*
* backhunt -- Reverse search for a previously acquired search string,
* starting at "." and proceeding toward the front of the buffer.
* If found "." is left pointing at the first character of the pattern
* (the last character that was matched).
*/
int PASCAL NEAR backhunt(f, n)
int f, n; /* default flag / numeric argument */
{
register int spoint = PTBEG;
register int status;
if (n < 0)
return (forwhunt(f, -n));
/* Make sure a pattern exists, or that we didn't switch
* into MAGIC mode after we entered the pattern.
*/
if (tap[0] == '\0') {
mlwrite(TEXT80);
/* "No pattern set" */
return FALSE;
}
#if MAGIC
if ((curwp->w_bufp->b_mode & MDMAGIC) && tapcm[0].mc_type == MCNIL) {
if (!mcstr())
return FALSE;
}
#endif
/*
* Do one extra search to get us past our current
* match, if the search type has us at the start
* of a match, instead of after a match.
*/
if (searchtype == SREND) {
spoint = PTEND;
if (lastflag & CFSRCH)
n = (n > 2)? (n + 1): 2;
}
#if MAGIC
if (magical && (curwp->w_bufp->b_mode & MDMAGIC))
status = mcscanner(REVERSE, spoint, n);
else
#endif
status = scanner(REVERSE, spoint, n);
/* Complain if not there.
*/
if (status == FALSE)
mlwrite(TEXT79);
/* "Not found" */
thisflag |= CFSRCH;
return (status);
}
#if MAGIC
/*
* mcscanner -- Search for a meta-pattern in either direction. If found,
* reset the "." to be at the start or just after the match string,
* and (perhaps) repaint the display.
*/
int PASCAL NEAR mcscanner(direct, beg_or_end, repeats)
int direct; /* which way to go.*/
int beg_or_end; /* put point at beginning or end of pattern.*/
int repeats; /* search repetitions.*/
{
MC *mcpatrn; /* pointer into pattern */
LINE *curline; /* current line during scan */
int curoff; /* position within current line */
/* If we are going in reverse, then the 'end' is actually
* the beginning of the pattern. Toggle it.
*/
beg_or_end ^= direct;
/* Another directional problem: if we are searching forwards,
* use the pattern in mcpat[]. Otherwise, use the reversed
* pattern in tapcm[].
*/
mcpatrn = (direct == FORWARD)? &mcpat[0]: &tapcm[0];
/* Setup local scan pointers to global ".".
*/
curline = curwp->w_dotp;
curoff = curwp->w_doto;
/* Scan each character until we hit the head link record.
*/
while (!boundry(curline, curoff, direct)) {
/* Save the current position in case we need to
* restore it on a match, and initialize matchlen to
* zero in case we are doing a search for replacement.
*/
matchline = curline;
matchoff = curoff;
matchlen = 0;
if (amatch(mcpatrn, direct, &curline, &curoff)) {
/* A SUCCESSFULL MATCH!!!
* Flag that we have moved,
* reset the global "." pointers.
*/
curwp->w_flag |= WFMOVE;
if (beg_or_end == PTEND) /* at end of string */
{
curwp->w_dotp = curline;
curwp->w_doto = curoff;
}
else /* at beginning of string */
{
curwp->w_dotp = matchline;
curwp->w_doto = matchoff;
}
/* If we're heading in reverse, set the "match"
* pointers to the start of the string, for savematch().
*/
if (direct == REVERSE) {
matchline = curline;
matchoff = curoff;
}
if (savematch() == ABORT)
return ABORT;
/* Continue scanning if we haven't found
* the nth match.
*/
if (--repeats <= 0)
return TRUE;
}
/* Advance the cursor.
*/
nextch(&curline, &curoff, direct);
}
return FALSE; /* We could not find a match.*/
}
/*
* amatch -- Search for a meta-pattern in either direction. Based on the
* recursive routine amatch() (for "anchored match") in
* Kernighan & Plauger's "Software Tools".
*/
int PASCAL NEAR amatch(mcptr, direct, pcwline, pcwoff)
register MC *mcptr; /* pattern to scan for */
int direct; /* which way to go.*/
LINE **pcwline; /* current line during scan */
int *pcwoff; /* position within current line */
{
register int c; /* character at current position */
LINE *curline; /* current line during scan */
int curoff; /* position within current line */
int n_chars; /* number of chars matched in a closure.*/
int cl_min; /* minimum number of chars matched in closure.*/
int cl_type; /* Which closure type?.*/
/* Set up lo